FreshMan писал(а): ну вот, сбылась мечта идиота, я написал примитивную прогу для своих будущих часов......ужас...
Не стыдно не знать, стыдно не учиться
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7331
FreshMan(Пользователь)
Специалист
Постов: 177
В ответ на: Мелкие вопросы 26.03.2012 23:11
Репутация: 1  
почему ? не ......, ну я согласен что это далеко не идеал, но......... а что вы можете предложить ?
Experience is the name everyone give to his mistakes.
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7332
FreshMan(Пользователь)
Специалист
Постов: 177
В ответ на: Мелкие вопросы 27.03.2012 00:07
Репутация: 1  
уже немного модернизировал
Code:
#include <mega8.h>
#include <delay.h>
#define kn_sec_reset PINC.0 // на 0 пин порта С подключена кнопка сброса секунд
#define kn_min_up PINC.1 // на 1 пин порта С подключена кнопка инкремента минут
#define anod_sec_l (PORTD|=(1<<4))
#define anod_sec_h (PORTD|=(1<<5))
#define anod_min_l (PORTD|=(1<<6))
#define anod_min_h (PORTD|=(1<<7))
unsigned int x;
unsigned char sec, min,i;
unsigned char number[4]; // в этом массиве мы будем хранить десятки и единици секунд и минут
//unsigned char znak[4]={16,32,64,128}; // в этом массиве мы храним номер анода индикатора
определенного разряда
interrupt [TIM0_OVF] void timer0_ovf_isr(void)// Timer 0 срабатывает каждую мс
{
// Reinitialize Timer 0 value
TCNT0=0x83;
// Place your code here
if(++x==1000) {sec++; x=0;};
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void)// Timer 1 срабатывает каждые 5мс
{
PORTD=0;
switch (i)
{
case 0:PORTD=number[i]; anod_sec_l; break;
case 1:PORTD=number[i]; anod_sec_h; break;
case 2:PORTD=number[i]; anod_min_l; break;
case 3:PORTD=number[i]; anod_min_h; break;
};
if (++i==4)i=0;
}
void main(void)
{
// Declare your local variables here
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T
PORTB=0x00;
DDRB=0x00;
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=P State0=P
PORTC=0x03;
DDRC=0x00;
// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0x00;
DDRD=0xFF;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
TCCR0=0x02;
TCNT0=0x83;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x02;
OCR1AL=0x71;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer/Counter 2 initialization
// Clock source: System Clock
// Clock value: Timer2 Stopped
// Mode: Normal top=FFh
// OC2 output: Disconnected
ASSR=0x00;
TCCR2=0x00;
TCNT2=0x00;
OCR2=0x00;
// External Interrupt(s) initialization
// INT0: Off
// INT1: Off
MCUCR=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x11;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// Global enable interrupts
#asm("sei")
while (1)
{
number[0]=sec%10; //в массив записываем остаток от деления преременной sec
number[1]=sec/10; // в массив записываем целую часть от деления преременной sec
number[2]=min%10; // в массив записываем остаток от деления преременной min
number[3]=min/10; // в массив записываем целую часть от деления преременной min
if (sec==60) {sec=0; min++;};
if (min==60) min=0;
if (kn_sec_reset==0) {delay_ms(10);sec=0; while(kn_sec_reset==0){}; delay_ms(10);};
if (kn_min_up==0) {delay_ms(10);min++; while(kn_min_up==0){}; delay_ms(10);};
};
}
Experience is the name everyone give to his mistakes.
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7333
ARV(Администратор)
Администратор
Постов: 2386
В ответ на: Мелкие вопросы 27.03.2012 08:27
Репутация: 176  
ужас в том, что я потратил столько времени, чтобы попытаться вас научить нормальному стилю программирования - и все впустую. жалко потраченного времени. невнятные переменные, тем более глобальные, вывод снова в куче с обработкой данных... про сам непродуманный алгоритм я пока молчу - это естественноо для начинающего, но стиль... я ведь объяснял....
Не стыдно не знать, стыдно не учиться
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7334
FreshMan(Пользователь)
Специалист
Постов: 177
В ответ на: Мелкие вопросы 27.03.2012 18:50
Репутация: 1  
и все впустую. простите,но дерзну с вами не согласится............., ничто в этой жизни не проходит безследно........., притчу о блудном сыне помните ? насчет переменных я ваш урок усвоил, просто зачастую я немогу придумать им внятные имена, например, переменная i, которая фигурирует у меня в программе так и осталась без внятного имени, ну незнаю я как ее толково назвать, поэтому и юзаю примитивные имена........, может подскажете вы ? переделал прогу, но часы стали идти ОЧЕНЬ медленно, где может быть моя ошибка ....?
Code:
#include <mega8.h>
#include <delay.h>
#define kn_sec_reset PINC.0 // на 0 пин порта С подключена кнопка сброса секунд
#define kn_min_up PINC.1 // на 1 пин порта С подключена кнопка инкремента минут
#define anod_sec_l (PORTD|=(1<<4))
#define anod_sec_h (PORTD|=(1<<5))
#define anod_min_l (PORTD|=(1<<6))
#define anod_min_h (PORTD|=(1<<7))
unsigned int var;
unsigned char sec, min,i;
unsigned char number[4]; // в этом массиве мы будем хранить десятки и единици секунд и минут
//unsigned char znak[4]={16,32,64,128}; // в этом массиве мы храним номер анода индикатора
определенного разряда
interrupt [TIM0_OVF] void timer0_ovf_isr(void)// Timer 0 срабатывает каждую мс
{
// Reinitialize Timer 0 value
TCNT0=0x83;
// Place your code here
if(++var==1000) {sec++; var=0;};
}
interrupt [TIM1_COMPA] void timer1_compa_isr(void)// Timer 1 срабатывает каждые 5мс
{
PORTD=0;
switch (i)
{
case 0:PORTD=number[i]; anod_sec_l; break;
case 1:PORTD=number[i]; anod_sec_h; break;
case 2:PORTD=number[i]; anod_min_l; break;
case 3:PORTD=number[i]; anod_min_h; break;
};
if (++i==4)i=0;
}
void mathematics(unsigned char sec, min)
{
number[0]=sec%10; //в массив записываем остаток от деления преременной sec
number[1]=sec/10; // в массив записываем целую часть от деления преременной sec
number[2]=min%10; // в массив записываем остаток от деления преременной min
number[3]=min/10; // в массив записываем целую часть от деления преременной min
}
void main(void)
{
// Port C initialization
// Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In
// State6=T State5=T State4=T State3=T State2=T State1=P State0=P
PORTC=0x03;
DDRC=0x00;
// Port D initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0
PORTD=0x00;
DDRD=0xFF;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
TCCR0=0x02;
TCNT0=0x83;
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 125,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Discon.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: Off
TCCR1A=0x00;
TCCR1B=0x0A;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x02;
OCR1AL=0x71;
OCR1BH=0x00;
OCR1BL=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x11;
// Analog Comparator initialization
// Analog Comparator: Off
// Analog Comparator Input Capture by Timer/Counter 1: Off
ACSR=0x80;
SFIOR=0x00;
// Global enable interrupts
#asm("sei")
while (1)
{
mathematics (min,sec);
if (sec==60) {sec=0; min++;};
if (min==60) min=0;
if (kn_sec_reset==0) {delay_ms(10);sec=0; while(kn_sec_reset==0){}; delay_ms(10);};
if (kn_min_up==0) {delay_ms(10);min++; while(kn_min_up==0){}; delay_ms(10);};
};
}
Experience is the name everyone give to his mistakes.
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7335
ARV(Администратор)
Администратор
Постов: 2386
В ответ на: Мелкие вопросы 27.03.2012 21:24
Репутация: 176  
видите ли... раз вы не можете придумать осмысленное название переменной, значит, и на самом деле в ее наличии нет никакого смысла! не скажу, что ВСЕ БЕЗ ИСКЛЮЧЕНИЯ переменные должны быть поименованы со смыслом, но тем не менее.
беда не в том, что переменная названа "i", а в том, что она вынесена в область глобальных переменных! в масштабе вашей программы нет для нее места, так что же она делает на виду у всех?! ее задача - где-то в недрах функции, обеспечивающей индикацию (прерывании то есть) обозначать номер текущего разряда. вам ведь в главном цикле не важно, какой именно в данный момент времени индикатор светится? значит, и переменная для этого не должна быть видима в главном цикле. я веду к тому, что она должна быть ЛОКАЛЬНОЙ переменной!
Code:
interrupt [TIM1_COMPA] void timer1_compa_isr(void)// Timer 1 срабатывает каждые 5мс
{
static unsigned char i = 0;
PORTD=0;
switch (i)
{
case 0:PORTD=number[i]; anod_sec_l; break;
case 1:PORTD=number[i]; anod_sec_h; break;
case 2:PORTD=number[i]; anod_min_l; break;
case 3:PORTD=number[i]; anod_min_h; break;
};
if (++i==4)i=0;
}
вот и все! но не совсем.
посмотрите на эту функцию, а конкретно - на оператор switch. скажите, чем ПРИНЦИПИАЛЬНО отличаются все 4 варианта case в этом операторе? ДА НИЧЕМ! они делают абсолютно однотипные действия, и отличаются только конкретным разрядом порта, который активируют! смотрите:
логично? понимаете, в чем разница? снова обращаю ваше внимание на замену волшебного числа 4 на константу IND_CNT - помните, почему так надо делать?
об остальном позже
Не стыдно не знать, стыдно не учиться
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7336
ARV(Администратор)
Администратор
Постов: 2386
В ответ на: Мелкие вопросы 27.03.2012 22:00
Репутация: 176  
теперь об остальном. matematics - это что за функция? не смотря на название, намекающее, что внутри идут какие-то вычисления, это функция ДЛЯ ВЫВОДА ЧИСЛА. вопрос знатокам - почему она названа математикой, а не выводом? 6 балло за правильный ответ! но это пустяк. не пустяк, что в этой функции вы снова не подумали о том, что разрядов на вашем индикаторе может быть не только 4. ваш алгоритм предусматривает работу с 4 индикаторами, а если их будет 5 или 6 - придется все переделывать. но зачем? ведь АЛГОРИТМ для разделения числа на разряды не зависит от числа этих разрядов! вот здесь я специально рассказывал о том, как это надо делать!
наконец, почему счет времени у вас ведется в основном цикле?! это совершенно неправильно! счет времени должен быть точным, а основной цикл занимается всем остальным, к точности чего требований не предъявляется. и даже в вашем случае не совсем понятен алгоритм счета времени - как-то шиворот навыворот записано простое: если секунд прошло 60, обнулить секунды и увеличить минуты, затем проверить: если минут прошло 60, то обнулить минуты и увеличить часы. затем проверить: если часов прошло 24, то обнулить часы и.... и т.д. в виде кода это очень логично записывается так:
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7337
ARV(Администратор)
Администратор
Постов: 2386
В ответ на: Мелкие вопросы 27.03.2012 22:02
Репутация: 176  
аналогично с работой с кнопками - все, о чем я вам толковал, все проигнорировано но повторять уже не буду: либо вы на самом деле хотите прислушиваться к моим советам, либо не хотите - это ваш выбор.
Не стыдно не знать, стыдно не учиться
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7338
FreshMan(Пользователь)
Специалист
Постов: 177
В ответ на: Мелкие вопросы 27.03.2012 23:22
Репутация: 1  
все замечания принимаю безпрекословно, каюсь и обещаю исправиться давайте по порядку: логично? понимаете, в чем разница? логика у вас железная !!! разница, как на меня, в том, что ваш код построен намного красивей и в нем нету "повторяемости"........, я же так понимаю ? на замену волшебного числа 4 на константу IND_CNT - помните, почему так надо делать? это для того чтобы в программе небыло непонятных чисел, а все носило осмысленные названия, дабы и через 100 лет наши потомки смогли уразуметь что мы им хотели сказать ....., ведь так ? константу IND_CNT нужно обявлять в начале проги ? вот так: # define IND_CNT 4 осмелюсь переспросить, ваш код
если нет, тогда я буду расписывать каждую строчку как я ее разумею.
Experience is the name everyone give to his mistakes.
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.
#7339
ARV(Администратор)
Администратор
Постов: 2386
В ответ на: Мелкие вопросы 28.03.2012 08:28
Репутация: 176  
FreshMan писал(а): логика у вас железная !!! разница, как на меня, в том, что ваш код построен намного красивей и в нем нету "повторяемости"........, я же так понимаю ? логика - она или железная, или отсутствует. красота - это следствие логичности кода. главное, в чем логика проявляется - это в максимальном соответствии того, что написано, тому, что определяет алгоритм. ведь алгоритм, если он правильно составлен, должен быть НЕЗАВИСИМ от количества обрабатываех им данных - в данном случае от количества разрядов на индикаторе: мы допускаем, что общие аноды(или катоды) индикатора идут в порту ПОСЛЕДОВАТЕЛЬНО, и составляем алгоритм так, что его реализация на Си остается НЕИЗМЕННОЙ для 1,2,3,4 и т.д. до 8 разрядов. вот в этом логика и красота.
когда вы решаете задчу, решать ее надо, как в алгебре - в виде формулы, а не в вид конечного числа. формула позволяет получить быстро ответ для любых исходных данных, а если решать в числах - всякий раз придется пересчитывать все-все-все. это совет.
это для того чтобы в программе небыло непонятных чисел, а все носило осмысленные названия, дабы и через 100 лет наши потомки смогли уразуметь что мы им хотели сказать ....., ведь так ?потомкам наверняка будет начхать на наши с вами коды... смысл констант в том, что назначение ей значения производится В ОДНОМ МЕСТЕ ПРОГРАММЫ, и затем, когда вы это значение меняете - всюду, где эта константа применялась, все меняется БЕЗ ОШИБОК. количество индикаторов у вас будет влиять на обработчик прерывания, на размер массива под выводимые символы, на алгоритм перевода числа в символы - всюду эта константа одна и та же. вы сделали вместо 4 ее значение 6 - и все участки кода СРАЗУ и ПРАВИЛЬНО стали обрабатывать эту ситуацию! Вы сами себе гарантируете, что число ошибок в вашей программе будет стремиться к минимуму! да и читать код вам будет проще.
что касается записи кода, то нет принципиальной разницы, что делать раньше - изменять положение выводимой позиции на индикатор, а затем обновлять содержимое индикатора, или наоборот. но в вашем варианте есть 2 участка, выполняющих одно и то же - это минус. беда не в том, что код повторяется, беда в том, что повторяется смысловй участок алгоритма - это черевато проблемами и ошибками, т.к. в случае чего вам придется менять код в двух местах и отслеживать, когла это надо и не надо.
как и ранее, логика должна быь железной: для достижения цели должен быть избран кратчайший путь, ведущий к успеху. простой пример: вам нужно подмести пол и пообедать. вариантов может быть два: 1. помыть руки, пообедать, подмести пол, помыть руки. 2. подмести пол, помыть руки, пообедать. как видите, мытье рук - необходимо в обоих случаях: перед приемом пищи и после того, как запачкали руки. расположив действия в правильном логическом порядке, вы исключаете лишнее мытье рук. и в вашем алгоритме все, что можт делаться один раз, должно делаться один раз.
Не стыдно не знать, стыдно не учиться
Для добавления сообщений Вы должны зарегистрироваться или авторизоваться.